package com.zzh.custom;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;

/**
 * @author zhangzhihao
 * @email zhangzhihao@gongjiangren.net
 * @date 2020-11-28
 * @desc
 */
public class CommonlyEditText extends ViewGroup {

    private static final int CODE = 1;
    private static final int COUNT = 2;

    public interface ConfigChildView {
        EditText getEdit(Context context);

        ImageView getClose(Context context);

        TextView getTiming(Context context);

        View getCountView(Context context);
    }

    public interface OnCodeListener {
        void onCodeStatus(EditText editText, ImageView closeView, TextView codeView, CodeStatus codeStatus);
    }

    public enum CodeStatus {
        /**
         * 开始获取验证码
         */
        START,
        /**
         * 结束获取验证码
         */
        END,
        /**
         * 获取验证码进行中
         */
        ONGOING
    }


    /**
     * 显示控制
     */
    //  mModel = COUNT时无效
    private boolean isShowClose = true;
    private boolean isShowTiming = false;
    //  mModel = CODE时无效
    private boolean isShowCount = false;

    /**
     * 显示的view
     */
    private EditText mEditText;
    private ImageView mCloseView;
    private TextView mTimingView;
    private View mCountRootView;
    private TextView mCountChangeView;
    private TextView mCountAllView;

    /**
     * 模式 1 验证码 2 计数
     */
    private int mModel = CODE;
    /**
     * EditView的输入限制
     */
    private int maxLength;
    private String hintText;
    private String editText;
    private int maxLine;
    private int centerStatus;

    /**
     * editText 文案
     */
    private int mTimingCount;
    private String mTimingStartText;
    private String mTimingEndText;
    /**
     * layoutId
     */
    private int mCloseLayoutId;
    private int mTimingLayoutId;
    private int mCountLayoutId;
    private int mEditLayoutId;

    /**
     * 配置使用的view
     */
    private ConfigChildView mConfigChildView;
    private OnCodeListener mOnCodeListener;
    private TextWatcher mAddTextWatcher;

    public void setConfigChildView(ConfigChildView configChildView) {
        mConfigChildView = configChildView;
    }

    public void setOnCodeListener(OnCodeListener onCodeListener) {
        mOnCodeListener = onCodeListener;
    }

    public void setAddTextWatcher(TextWatcher addTextWatcher) {
        mAddTextWatcher = addTextWatcher;
    }

    public CommonlyEditText(Context context) {
        this(context, null);
    }

    public CommonlyEditText(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public CommonlyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CommonlyEditText, 0, 0);
        mModel = typeArray.getInt(R.styleable.CommonlyEditText_etModel, CODE);
        maxLength = typeArray.getInt(R.styleable.CommonlyEditText_etMaxLength, 1000);
        hintText = typeArray.getString(R.styleable.CommonlyEditText_etHint);
        editText = typeArray.getString(R.styleable.CommonlyEditText_etText);
        maxLine = typeArray.getInt(R.styleable.CommonlyEditText_etMaxLine, 1);
        centerStatus = typeArray.getInt(R.styleable.CommonlyEditText_etGravity, 1);
        isShowClose = typeArray.getBoolean(R.styleable.CommonlyEditText_etShowClose, true);
        isShowTiming = typeArray.getBoolean(R.styleable.CommonlyEditText_etShowTiming, false);
        isShowCount = typeArray.getBoolean(R.styleable.CommonlyEditText_etShowCount, false);
        mTimingCount = typeArray.getInt(R.styleable.CommonlyEditText_etTimingCount, 60);
        mTimingStartText = typeArray.getString(R.styleable.CommonlyEditText_etTimingStartText);
        mTimingEndText = typeArray.getString(R.styleable.CommonlyEditText_etTimingEndText);
        mCloseLayoutId = typeArray.getResourceId(R.styleable.CommonlyEditText_etCloseLayoutId, R.layout.commonly_edit_text_close);
        mTimingLayoutId = typeArray.getResourceId(R.styleable.CommonlyEditText_etCloseLayoutId, R.layout.commonly_edit_text_timing);
        mCountLayoutId = typeArray.getResourceId(R.styleable.CommonlyEditText_etCloseLayoutId, R.layout.commonly_edit_text_count);
        mEditLayoutId = typeArray.getResourceId(R.styleable.CommonlyEditText_etCloseLayoutId, R.layout.commonly_edit_text_edit);
        typeArray.recycle();
        initView(context);
        configChildView(context);
        configAddView();
        configViewClick();
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (getMeasuredWidth() <= 0) {
            return;
        }
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        int top = getPaddingTop();
        int bottom = height - getPaddingBottom();
        int left = getPaddingLeft();
        int right = width - getPaddingRight();
        if (mModel == CODE) {
            if (isShowTiming) {
                int deviationHeight = ((bottom - top) - mTimingView.getMeasuredHeight()) / 2 + getPaddingTop();
                mTimingView.layout(
                        right - mTimingView.getMeasuredWidth(),
                        deviationHeight,
                        right,
                        deviationHeight + mTimingView.getMeasuredHeight()
                );
                right = right - mTimingView.getMeasuredWidth();
            }
            if (isShowClose) {
                int deviationHeight = ((bottom - top) - mCloseView.getMeasuredHeight()) / 2 + getPaddingTop();
                mCloseView.layout(
                        right - mCloseView.getMeasuredWidth(),
                        deviationHeight,
                        right,
                        deviationHeight + mCloseView.getMeasuredHeight()
                );
                right = right - mCloseView.getMeasuredWidth();
            }
            int deviationHeight = ((bottom - top) - mEditText.getMeasuredHeight()) / 2 + getPaddingTop();
            mEditText.layout(left,
                    deviationHeight,
                    right,
                    deviationHeight + mEditText.getMeasuredHeight());
        } else if (mModel == COUNT) {
            if (isShowCount) {
                mCountRootView.layout(
                        right - mCountRootView.getMeasuredWidth(),
                        bottom - mCountRootView.getMeasuredHeight(),
                        right,
                        bottom
                );
                bottom = bottom - mCountRootView.getMeasuredHeight();
            }
            mEditText.layout(left,
                    top,
                    right,
                    bottom);
        }
    }


    private void initView(Context context) {
        if (mConfigChildView != null) {
            mEditText = mConfigChildView.getEdit(context);
            mCloseView = mConfigChildView.getClose(context);
            mTimingView = mConfigChildView.getTiming(context);
            mCountRootView = mConfigChildView.getCountView(context);
        }
        if (mEditText == null) {
            mEditText = (EditText) LayoutInflater.from(context).inflate(mEditLayoutId, null, false);
        }
        if (mCloseView == null) {
            mCloseView = (ImageView) LayoutInflater.from(context).inflate(mCloseLayoutId, null, false);
        }
        if (mTimingView == null) {
            mTimingView = (TextView) LayoutInflater.from(context).inflate(mTimingLayoutId, null, false);
        }
        if (mCountRootView == null) {
            mCountRootView = LayoutInflater.from(context).inflate(mCountLayoutId, null, false);
        }
        mCountChangeView = mCountRootView.findViewById(R.id.changeCount);
        mCountAllView = mCountRootView.findViewById(R.id.allCount);
    }

    private void configChildView(Context context) {
        mEditText.setMaxLines(maxLine);
        mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
        mEditText.setHint(hintText);
        mEditText.setText(editText);
        mEditText.setGravity(centerStatus == 1 ? Gravity.CENTER_VERTICAL :
                centerStatus == 2 ? Gravity.CENTER_HORIZONTAL :
                        centerStatus == 3 ? Gravity.CENTER :
                                centerStatus == 4 ? Gravity.START :
                                        Gravity.CENTER_VERTICAL);
        mTimingView.setText(TextUtils.isEmpty(mTimingStartText) ? "获取验证码" : mTimingStartText);
    }

    public void resetView() {
        mHandler.removeCallbacksAndMessages(null);
        removeAllViews();
        initView(getContext());
        configChildView(getContext());
        configAddView();
        configViewClick();
        invalidate();
    }

    private void configAddView() {
        if (mModel == CODE) {
            addView(mEditText);
            addView(mCloseView);
            addView(mTimingView);
        } else if (mModel == COUNT) {
            addView(mEditText);
            addView(mCountRootView);
        } else {
            throw new IllegalArgumentException("扯淡呢");
        }
    }

    private void configViewClick() {
        if (mModel == CODE) {
            mCloseView.setOnClickListener(v -> mEditText.setText(""));
            mTimingView.setOnClickListener(v -> {
                Message message = mHandler.obtainMessage();
                message.what = HAN_START;
                mHandler.sendMessage(message);
            });
        } else if (mModel == COUNT) {
            if (isShowCount) {
                mEditText.addTextChangedListener(mTextWatcher);
                mCountAllView.setText(String.format("/%d", maxLength));
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        measureChildren(widthMeasureSpec, heightMeasureSpec);
    }

    private TextWatcher mTextWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            if (mAddTextWatcher != null) {
                mAddTextWatcher.beforeTextChanged(s, start, count, after);
            }
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (mAddTextWatcher != null) {
                mAddTextWatcher.onTextChanged(s, start, before, count);
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
            if (mAddTextWatcher != null) {
                mAddTextWatcher.afterTextChanged(s);
            }
            if (isShowCount) {
                mCountChangeView.setText(String.valueOf(s.length()));
            }
        }
    };

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
        }
        mHandler = null;
    }

    private static final int HAN_START = 1;
    private static final int HAN_END = 2;
    private static final int HAN_ONGOING = 3;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            CodeStatus codeStatus = null;
            switch (msg.what) {
                case HAN_START:
                    codeStatus = CodeStatus.START;
                    Message messageStart = mHandler.obtainMessage();
                    messageStart.what = HAN_ONGOING;
                    messageStart.arg1 = mTimingCount - 2;
                    mHandler.sendMessageDelayed(messageStart, 1000);
                    mTimingView.setClickable(false);
                    mTimingView.setText(String.format("%ds", mTimingCount - 1));
                    break;
                case HAN_ONGOING:
                    codeStatus = CodeStatus.ONGOING;
                    int count = msg.arg1;
                    if (count <= 0) {
                        Message message = mHandler.obtainMessage();
                        message.what = HAN_END;
                        mHandler.sendMessage(message);
                        break;
                    }
                    Message message = mHandler.obtainMessage();
                    message.what = HAN_ONGOING;
                    message.arg1 = count - 1;
                    mHandler.sendMessageDelayed(message, 1000);
                    mTimingView.setText(String.format("%ds", count));
                    break;
                case HAN_END:
                    codeStatus = CodeStatus.END;
                    mTimingView.setClickable(true);
                    mTimingView.setText(TextUtils.isEmpty(mTimingEndText) ? "再次获取验证码" : mTimingEndText);
                    break;
                default:
                    break;
            }
            if (mOnCodeListener != null && codeStatus != null) {
                mOnCodeListener.onCodeStatus(mEditText, mCloseView, mTimingView, codeStatus);
            }
        }
    };

}
